﻿#pragma once

#include "../MirEnvir/Envir.h"
#include "../MessageQueue.h"
#include "../../Shared/Packet.h"
#include "../MirDatabase/AccountInfo.h"
#include "../MirObjects/PlayerObject.h"
#include "../../Shared/Data/ItemData.h"
#include "../MirDatabase/QuestInfo.h"
#include "../MirDatabase/RecipeInfo.h"
#include "../../Shared/ClientPackets.h"
#include <string>
#include <vector>
#include <deque>
#include <limits>
#include <any>
#include <mutex>
#include "../../stringhelper.h"

using namespace Server::MirDatabase;
using namespace Server::MirEnvir;
using namespace Server::MirObjects;
namespace C = ClientPackets;
namespace S = ServerPackets;

namespace Server::MirNetwork
{
    enum class GameStage
    {
        None,
        Login,
        Select,
        Game,
        Disconnected
    };

    class MirConnection
    {
    public:
        virtual ~MirConnection()
        {
            delete _client;
            delete _receiveList;
            delete _sendList;
            delete Account;
            delete Player;
        }

    protected:
        static Server::MirEnvir::Envir *getEnvir();

        static Server::MessageQueue *getMessageQueue();

    public:
        const int SessionID;
        const std::string IPAddress;

        GameStage Stage = static_cast<GameStage>(0);

    private:
        TcpClient *_client;
        ConcurrentQueue<Packet*> *_receiveList;
        ConcurrentQueue<Packet*> *_sendList;
        std::deque<Packet*> _retryList;

        bool _disconnecting = false;
    public:
        bool Connected = false;
        bool getDisconnecting() const;
        void setDisconnecting(bool value);
        const long long TimeConnected;
        long long TimeDisconnected = 0, TimeOutTime = 0;

    private:
        std::vector<unsigned char> _rawData = std::vector<unsigned char>(0);
        std::vector<unsigned char> _rawBytes = std::vector<unsigned char>(8 * 1024);

    public:
        AccountInfo *Account;
        PlayerObject *Player;
        std::vector<ItemInfo*> SentItemInfo = std::vector<ItemInfo*>();
        std::vector<QuestInfo*> SentQuestInfo = std::vector<QuestInfo*>();
        std::vector<RecipeInfo*> SentRecipeInfo = std::vector<RecipeInfo*>();
        std::vector<UserItem*> SentChatItem = std::vector<UserItem*>(); //TODO - Add Expiry time

        bool StorageSent = false;


//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to 'ToString':
        MirConnection(int sessionID, TcpClient *client);

    private:
        void BeginReceive();
        void ReceiveData(IAsyncResult *result);
        void BeginSend(std::vector<unsigned char> &data);
        void SendData(IAsyncResult *result);

    public:
        void Enqueue(Packet *p);

        void Process();
    private:
        void ProcessPacket(Packet *p);

    public:
        void SoftDisconnect(unsigned char reason);
        void Disconnect(unsigned char reason);
        void SendDisconnect(unsigned char reason);

    private:
        void ClientVersion(C::ClientVersion *p);
        void ClientKeepAlive(C::KeepAlive *p);
        void NewAccount(C::NewAccount *p);
        void ChangePassword(C::ChangePassword *p);
        void Login(C::Login *p);
        void NewCharacter(C::NewCharacter *p);
        void DeleteCharacter(C::DeleteCharacter *p);
        void StartGame(C::StartGame *p);

    public:
        void LogOut();

    private:
        void Turn(C::Turn *p);
        void Walk(C::Walk *p);
        void Run(C::Run *p);

        void Chat(C::Chat *p);

        void MoveItem(C::MoveItem *p);
        void StoreItem(C::StoreItem *p);

        void DepositRefineItem(C::DepositRefineItem *p);

        void RetrieveRefineItem(C::RetrieveRefineItem *p);

        void RefineCancel(C::RefineCancel *p);

        void RefineItem(C::RefineItem *p);

        void CheckRefine(C::CheckRefine *p);

        void ReplaceWedRing(C::ReplaceWedRing *p);

        void DepositTradeItem(C::DepositTradeItem *p);

        void RetrieveTradeItem(C::RetrieveTradeItem *p);
        void TakeBackItem(C::TakeBackItem *p);
        void MergeItem(C::MergeItem *p);
        void EquipItem(C::EquipItem *p);
        void RemoveItem(C::RemoveItem *p);
        void RemoveSlotItem(C::RemoveSlotItem *p);
        void SplitItem(C::SplitItem *p);
        void UseItem(C::UseItem *p);
        void DropItem(C::DropItem *p);
        void DropGold(C::DropGold *p);
        void PickUp();
        void Inspect(C::Inspect *p);
        void ChangeAMode(C::ChangeAMode *p);
        void ChangePMode(C::ChangePMode *p);
        void ChangeTrade(C::ChangeTrade *p);
        void Attack(C::Attack *p);
        void RangeAttack(C::RangeAttack *p);
        void Harvest(C::Harvest *p);

        void CallNPC(C::CallNPC *p);

        void BuyItem(C::BuyItem *p);
        void CraftItem(C::CraftItem *p);
        void SellItem(C::SellItem *p);
        void RepairItem(C::RepairItem *p);
        void BuyItemBack(C::BuyItemBack *p);
        void SRepairItem(C::SRepairItem *p);
        void MagicKey(C::MagicKey *p);
        void Magic(C::Magic *p);

        void SwitchGroup(C::SwitchGroup *p);
        void AddMember(C::AddMember *p);
        void DelMember(C::DelMember *p);
        void GroupInvite(C::GroupInvite *p);

        void TownRevive();

        void SpellToggle(C::SpellToggle *p);
        void ConsignItem(C::ConsignItem *p);
        void MarketSearch(C::MarketSearch *p);
        void MarketRefresh();

        void MarketPage(C::MarketPage *p);
        void MarketBuy(C::MarketBuy *p);
        void MarketSellNow(C::MarketSellNow *p);

        void MarketGetBack(C::MarketGetBack *p);
        void RequestUserName(C::RequestUserName *p);
        void RequestChatItem(C::RequestChatItem *p);
        void EditGuildMember(C::EditGuildMember *p);
        void EditGuildNotice(C::EditGuildNotice *p);
        void GuildInvite(C::GuildInvite *p);
        void RequestGuildInfo(C::RequestGuildInfo *p);
        void GuildNameReturn(C::GuildNameReturn *p);
        void GuildStorageGoldChange(C::GuildStorageGoldChange *p);
        void GuildStorageItemChange(C::GuildStorageItemChange *p);
        void GuildWarReturn(C::GuildWarReturn *p);


        void MarriageRequest(C::MarriageRequest *p);

        void MarriageReply(C::MarriageReply *p);

        void ChangeMarriage(C::ChangeMarriage *p);

        void DivorceRequest(C::DivorceRequest *p);

        void DivorceReply(C::DivorceReply *p);

        void AddMentor(C::AddMentor *p);

        void MentorReply(C::MentorReply *p);

        void AllowMentor(C::AllowMentor *p);

        void CancelMentor(C::CancelMentor *p);

        void TradeRequest(C::TradeRequest *p);
        void TradeGold(C::TradeGold *p);
        void TradeReply(C::TradeReply *p);
        void TradeConfirm(C::TradeConfirm *p);
        void TradeCancel(C::TradeCancel *p);
        void EquipSlotItem(C::EquipSlotItem *p);

        void FishingCast(C::FishingCast *p);

        void FishingChangeAutocast(C::FishingChangeAutocast *p);

        void AcceptQuest(C::AcceptQuest *p);

        void FinishQuest(C::FinishQuest *p);

        void AbandonQuest(C::AbandonQuest *p);

        void ShareQuest(C::ShareQuest *p);

        void AcceptReincarnation();

        void CancelReincarnation();

        void CombineItem(C::CombineItem *p);

        void Awakening(C::Awakening *p);

        void AwakeningNeedMaterials(C::AwakeningNeedMaterials *p);

        void DisassembleItem(C::DisassembleItem *p);

        void DowngradeAwakening(C::DowngradeAwakening *p);

        void ResetAddedItem(C::ResetAddedItem *p);

    public:
        void SendMail(C::SendMail *p);

        void ReadMail(C::ReadMail *p);

        void CollectParcel(C::CollectParcel *p);

        void DeleteMail(C::DeleteMail *p);

        void LockMail(C::LockMail *p);

        void MailCost(C::MailCost *p);

    private:
        void RequestIntelligentCreatureUpdates(C::RequestIntelligentCreatureUpdates *p);

        void UpdateIntelligentCreature(C::UpdateIntelligentCreature *p); //IntelligentCreature

        void IntelligentCreaturePickup(C::IntelligentCreaturePickup *p); //IntelligentCreature

        void AddFriend(C::AddFriend *p);

        void RemoveFriend(C::RemoveFriend *p);

        void AddMemo(C::AddMemo *p);
        void GuildBuffUpdate(C::GuildBuffUpdate *p);
        void GameshopBuy(C::GameshopBuy *p);

        void NPCConfirmInput(C::NPCConfirmInput *p);

    public:
        std::vector<std::vector<unsigned char>> Image = std::vector<std::vector<unsigned char>>();

    private:
        void ReportIssue(C::ReportIssue *p);
        void GetRanking(C::GetRanking *p);

        void Opendoor(C::Opendoor *p);

        void GetRentedItems();

        void ItemRentalRequest();

        void ItemRentalFee(C::ItemRentalFee *p);

        void ItemRentalPeriod(C::ItemRentalPeriod *p);

        void DepositRentalItem(C::DepositRentalItem *p);

        void RetrieveRentalItem(C::RetrieveRentalItem *p);

        void CancelItemRental();

        void ItemRentalLockFee();

        void ItemRentalLockItem();

        void ConfirmItemRental();
    };
}
